#ifndef QDOWNLOADHANDLER_H
#define QDOWNLOADHANDLER_H

#include <QObject>
#include <QSerialPort>
#include <QThread>
#include <QFile>
#include <QDebug>
#include <QTimer>
#include <QCryptographicHash>

#define ACK ((quint8)0x79)
#define NACK ((quint8)0x1F)

typedef struct
{
    const char* name;
    quint32 uniqueId;
    quint32 flashCapacity;
}chip_type_t;

class QDownloadHandler : public QObject
{
    Q_OBJECT
public:
    explicit QDownloadHandler(QObject *parent = nullptr);
    virtual ~QDownloadHandler();
    void setPortName(const QString& portName);
    void setFileName(const QString& fileName);
    void setChipName(const QString& chipName);
    void setBaudrate(int baudrate);
    void setReadProtcet(bool enable);
    bool isDownloading();

signals:
    void error(QString msg);
    void information(QString msg);
    void progress(int value);

public slots:
    void download();

private:
    QSerialPort* serial;
    QString _portName;
    QString _fileName;
    QString _chipName;
    int _baudrate;
    int chipIndex;
    bool _isDownloading;
    bool _isReadProtect;

    const chip_type_t chipType[10] =
    {
        {"STM32F0", 0x1FFFF7AC, 0x1FFFF7CC},
        {"STM32F1", 0x1FFFF7E8, 0x1FFFF7E0},
        {"STM32F2", 0x1FFF7A10, 0x1FFF7A22},
        {"STM32F3", 0x1FFFF7AC, 0x1FFFF7CC},
        {"STM32F4", 0x1FFF7A10, 0x1FFFFA22},
        {"STM32F7", 0x1FF0F420, 0x1FFFF442},
        {"STM32L0", 0x1FF80050, 0x1FF8007C},
        {"STM32L1", 0x1FF80050, 0x1FF8004C},
        {"STM32L4", 0x1FFF7590, 0x1FFF75E0},
        {"STM32H7", 0x1FF0F420, 0x1FF0F442},
    };

private:
    void msleep(int nms);
    int write(const void* buf, quint32 len);
    int read(void* buf, quint32 len);
    quint8 checksum(const void* buf, quint32 len);
    int writeBlock(quint32 addr, const void* buf, quint32 len);
    int readBlock(quint32 addr, void* buf, quint8 len);
    int eraseFull(void);
    int connectToDevice(void);
    int goRun(quint32 adddr);
    int readPID(quint8* id, quint8* len);
    int readUID(uint32_t addr, quint8 *id, quint8 *len);
    int readFlashCapacity(uint32_t addr, quint32* capacity);
    int readCmd(quint8* protocolVersion, quint8* cmd, quint8* num);
    int setReadoutProtect(bool enable);
    int setWriteProtect(bool enable);
    int enterIspMode();
    void exitIspMode();
};

#endif // QDOWNLOADHANDLER_H
